home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
201
/
201.xpi
/
modules
/
utils.jsm
< prev
next >
Wrap
Text File
|
2010-01-11
|
5KB
|
239 lines
/* You may find the license in the LICENSE file */
const EXPORTED_SYMBOLS = [
'atos',
'newUUIDString',
'range',
'hexdigest',
'merge',
'clone',
'formatNumber',
'formatTimeDelta',
'getTimestamp',
'naturalSort',
];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
/**
* returns a new UUID in string representation
* @return String UUID
* @author Nils
*/
function newUUIDString() {
let uuidgen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
newUUIDString = function() {
return uuidgen.generateUUID().toString();
}
return newUUIDString();
}
/**
* Range generator (python style). Difference: step direction is initialized accordingly if corresponding parameter is omitted.
* @param start Optional. Start value (default: 0)
* @param stop Stop value (exclusive)
* @param step Optional. Step value (default: 1/-1)
* @author Nils
*/
function range() {
if (arguments.length == 0) {
throw Components.results.NS_ERROR_INVALID_ARG;
}
let start = 0, stop = new Number(arguments[0]), step;
if (arguments.length >= 2) {
start = stop;
stop = new Number(arguments[1]);
}
if (arguments.length >= 3) {
step = new Number(arguments[2]);
}
else {
step = stop - start > 0 ? 1 : -1;
}
if (!isFinite(start) || !isFinite(stop) || !isFinite(step) || step == 0) {
throw Cr.NS_ERROR_INVALID_ARG;
}
if ((stop - start) / step < 0) {
// negative range
return;
}
stop += -Math.abs(step) / step;
stop += step - ((stop - start) % step);
for (; start != stop; start += step) {
yield start;
}
}
/**
* Builds the hexdigest of (binary) data
* @param {Object} data
* @return {String} hexdigest
*/
function hexdigest(data) {
data = data.toString();
return [('0' + data.charCodeAt(i).toString(16)).slice(-2) for (i in range(data.length))].join('');
}
/**
* Merges the enumeratable properties of two objects
* @param {Object} me Object that has the properties added the properties
* @param {Object} that Object of which the properties are taken
*/
function merge(me, that) {
for (let c in that) {
me[c] = that[c];
}
}
/**
* (Almost) Clones an object. Not instanceof safe :p
* @param {Object} obj
* @return {Object} Copy of obj
*/
function clone(obj) {
var rv = {};
merge(rv, obj);
merge(rv.prototype, this.prototype);
rv.constructor = this.constructor;
return rv;
}
/**
* Cast non-strings to strings (using toSource if required instead of toString()
* @param {Object} data
*/
function atos(data) {
if (typeof(data) == 'string') {
return data;
}
if (data instanceof String || typeof(data) == 'object') {
try {
return data.toSource();
}
catch (ex) {
// fall-trough
}
}
return data.toString();
}
/**
* Head-Pads a number so that at it contains least "digits" digits.
* @param {Object} num The number in question
* @param {Object} digits Number of digits the results must contain at least
*/
function formatNumber(num, digits) {
let rv = atos(num);
digits = Number(digits);
if (!isFinite(digits)) {
digits = 3;
}
for (let i = rv.length; i < digits; ++i) {
rv = '0' + rv;
}
return rv;
}
/**
* Formats a time delta (seconds)
* @param {Number} delta in seconds
* @return {String} formatted result
*/
function formatTimeDelta(delta) {
let rv = (delta < 0) ? '-' : '';
delta = Math.abs(delta);
let h = Math.floor(delta / 3600);
let m = Math.floor((delta % 3600) / 60);
let s = Math.floor(delta % 60);
if (h) {
rv += formatNumber(h, 2) + ':';
}
return rv + formatNumber(m, 2) + ':' + formatNumber(s, 2);
}
/**
* Converts a Datestring into an integer timestamp.
* @param {Object} str Datestring or null for current time.
*/
function getTimestamp(str) {
if (!str) {
return Date.now();
}
let rv = Date.parse(atos(str));
if (!isFinite(rv)) {
throw new Error('invalid date');
}
return rv;
}
function naturalSort(arr, mapper) {
if (typeof mapper != 'function' && !(mapper instanceof Function)) {
mapper = function(e) e;
}
let isDigit = function(a, i) {
i = a[i];
return i >= '0' && i <= '9';
};
let compare = function(a, b) {
return a === b ? 0 : (a < b ? -1 : 1);
}
arr = arr.map(
function(b) {
let e = mapper(b);
if (e == null || e == undefined || typeof e == 'number') {
return {elem: b, chunks: [e]};
}
let a = e.toString().replace(/\b(?:a|one|the)\b/g, ' ').replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ').toLowerCase();
let len = a.length;
if (!len) {
return {elem: b, chunks: [a]};
}
let rv = [];
let last = isDigit(a, 0);
let cur = last;
start = 0;
for (let i = 0; i < len; ++i) {
cur = isDigit(a, i);
if (cur != last) {
rv.push(cur ? a.substr(start, i - start) : Number(a.substr(start, i - start)));
start = i;
last = cur;
}
}
if (!rv.length || len - start != 1) {
rv.push(cur ? Number(a.substr(start)) : a.substr(start));
}
return {elem: b, chunks: rv};
}
);
arr.sort(
function (a, b) {
let ai, bi;
[a, b] = [a.chunks, b.chunks];
let m = Math.max(a.length, b.length);
for (let i = 0; i < m; ++i) {
let ai = a[i], bi = b[i];
let rv = compare(typeof ai, typeof bi);
if (rv) {
return rv;
}
rv = compare(ai, bi);
if (rv) {
return rv;
}
}
return a.length - b.length;
}
);
return arr.map(function(a) a.elem);
}